#include "RenderView.h"
#include <vector>
#include <GL/glut.h>
#include <limits>

#define PI 3.14159265

void RenderView::ReadDataFromFile(string _fileName)
{
	o_IOManager.ReadDataToDatabase(_fileName);
}

void RenderView::CalculateFunctionValue()
{
	o_IOManager.CalculateFunctionValue();
}

void RenderView::SetNeighborList()
{
    o_IOManager.SetNeighborList();
}

void RenderView::CalculateLocalMaxMin()
{
    o_IOManager.CalculateLocalMaxMin();
}

void RenderView::CalculateLocalSaddle()
{
	o_IOManager.CalculateLocalSaddle();
}

void RenderView::RenderOffModel()
{
	vector<Vertex>* l_vertexList = o_IOManager.GetVertexDataArray();
	vector<Face>* l_faceList = o_IOManager.GetFaceDataArray();

	for (int i = 0; i < l_faceList->size(); ++i)
	{
		Face _face = l_faceList->at(i);
		glBegin(GL_POLYGON);
		for (int j = 0; j < _face.numVertex; ++j)
		{
			glColor3d(1.0, 1.0, 1.0);
			Vertex v = l_vertexList->at(_face.listVertexIndex.at(j));
			glVertex3d(v.x, v.y, v.z);
		}
		glEnd();
		//		
		glBegin(GL_LINE_LOOP);
		for (int j = 0; j < _face.numVertex; ++j)
		{
			glColor3d(1.0, 0.0, 0.0);
			Vertex v = l_vertexList->at(_face.listVertexIndex.at(j));
			glVertex3d(v.x, v.y, v.z);
		}
		glEnd();
	}
}

void RenderView::RenderUnfoldModel()
{
	vector<GraphNode> * faceGraph = o_IOManager.GetGraph();
	for (int i = 0; i < faceGraph->size(); ++i)
	{
		GraphNode * n = &faceGraph->at(i);
		glBegin(GL_POLYGON);
			glColor3d(1.0, 1.0, 1.0);
			glVertex3d(n->unfoldV1.x + n->offset, n->unfoldV1.y, 0.0);
			glVertex3d(n->unfoldV2.x + n->offset, n->unfoldV2.y, 0.0);
			glVertex3d(n->unfoldV3.x + n->offset, n->unfoldV3.y, 0.0);
		glEnd();
		//		
		glBegin(GL_LINE_LOOP);
			glColor3d(1.0, 0.0, 0.0);
			glVertex3d(n->unfoldV1.x + n->offset, n->unfoldV1.y, 0.0);
			glVertex3d(n->unfoldV2.x + n->offset, n->unfoldV2.y, 0.0);
			glVertex3d(n->unfoldV3.x + n->offset, n->unfoldV3.y, 0.0);
		glEnd();
	}
}

void RenderView::RenderLocalMaxMin()
{
    vector<Vertex>* l_vertexList = o_IOManager.GetVertexDataArray();
    vector<int> * l_LocalMaxList = o_IOManager.GetLocalMaxList();
    vector<int> * l_LocalMinList = o_IOManager.GetLocalMinList();
    for (int i = 0; i < l_LocalMaxList->size(); ++i)
    {
        Vertex * v = &l_vertexList->at(l_LocalMaxList->at(i));
        glPushMatrix();
        glTranslated(v->x, v->y, v->z);
        glColor3d(0.0, 1.0, 0.0);
        glutSolidSphere(0.02, 10, 10);
        glPopMatrix();
    }

    for (int i = 0; i < l_LocalMinList->size(); ++i)
    {
        Vertex * v = &l_vertexList->at(l_LocalMinList->at(i));
        glPushMatrix();
        glTranslated(v->x, v->y, v->z);
        glColor3d(0.0, 0.0, 1.0);
        glutSolidSphere(0.02, 10, 10);
        glPopMatrix();
    }
}

void RenderView::RenderLocalSaddle()
{
	vector<Vertex>* l_vertexList = o_IOManager.GetVertexDataArray();
	vector<int> * l_LocalSaddleList = o_IOManager.GetLocalSaddleList();
	
	for (int i = 0; i < l_LocalSaddleList->size(); ++i)
	{
		Vertex * v = &l_vertexList->at(l_LocalSaddleList->at(i));
		glPushMatrix();
		glTranslated(v->x, v->y, v->z);
		glColor3d(1.0, 1.0, 0.0);
		glutSolidSphere(0.01, 10, 10);
		glPopMatrix();
	}
}

void RenderView::CalculateTraceLine()
{
    o_IOManager.CalculateTraceList();
}
void RenderView::RenderTraceLine()
{
	vector<vector<int>> * lineList = o_IOManager.GetTraceLineList();
	vector<Vertex>* l_vertexList = o_IOManager.GetVertexDataArray();

	for (int i = 0; i < lineList->size(); ++i)
	{
		glColor3d(0.0, 0.0, 1.0);
		glBegin(GL_LINE_STRIP);		
		for (int j = 0; j < lineList->at(i).size(); ++j)
		{
			Vertex v = l_vertexList->at(lineList->at(i).at(j));
			glVertex3d(v.x, v.y, v.z);
		}
		glEnd();
	}
}

void RenderView::SimplifyMesh()
{
	o_IOManager.SmoothenSurface();
	o_IOManager.SimplifyMesh();
}

void RenderView::CalculateUnfoldAngle()
{
    o_IOManager.CalculateUnfoldAngle();
}

void RenderView::RenderUnfoldShaderModel()
{
    vector<Vertex>* l_vertexList = o_IOManager.GetVertexDataArray();
    vector<Face>* l_faceList = o_IOManager.GetFaceDataArray();
    double maxShader = -10*PI;
    double minShader = 10*PI;
    for (int i = 0; i < l_vertexList->size(); ++i)
    {
        if (maxShader < l_vertexList->at(i).unfoldAngle)
        {
            maxShader = l_vertexList->at(i).unfoldAngle;
        }
        if (minShader > l_vertexList->at(i).unfoldAngle)
        {
            minShader = l_vertexList->at(i).unfoldAngle;
        }
    }
	minShader = 0;
	maxShader = 4*PI;

    for (int i = 0; i < l_faceList->size(); ++i)
    {
        Face _face = l_faceList->at(i);
        glBegin(GL_POLYGON);
        for (int j = 0; j < _face.numVertex; ++j)
        {
            Vertex v = l_vertexList->at(_face.listVertexIndex.at(j));
            double shader = (v.unfoldAngle + minShader) / (maxShader + minShader);
            double avg = (maxShader + minShader) / 2;
            if (v.unfoldAngle < avg)
            {
                glColor3d(0.0, shader, 0.0);
            }
            else
            {
                glColor3d(shader, 0.0, 0.0);
            }
            glVertex3d(v.x, v.y, v.z);
        }
        glEnd();
    }
}

void RenderView::SetFaceNeighborList()
{
	o_IOManager.SetFaceNeighborList();
}

void RenderView::BuildGraph()
{
	o_IOManager.BuildGraphFromMesh();
}

void RenderView::BreakGraph()
{
	o_IOManager.BreakGraphToTree();
}

void RenderView::CalculateUnfoldCoord()
{
	o_IOManager.CalculateUnfoldCoord();
}

void RenderView::SegmentGraph()
{
	o_IOManager.SegmentGraph();
}